package demo.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;

import com.sun.org.apache.bcel.internal.generic.Select;

/**
 * @program: mccken-collect
 * @description:
 * @author: mccken
 * @create: 2021-10-10 23:54
 **/
public class MyNIOServer {

	private static Selector selector;
	
	private static LinkedBlockingQueue<SelectionKey> requestQueue;
	
	private static ExecutorService threadPool;
	
	
	public static void main(String[] args) {
		init();
		lesten();
	}

	private static void lesten() {
		while (true) {
			
			try {
				selector.select();
				Set<SelectionKey> keys = selector.selectedKeys();
				Iterator<SelectionKey> iterator = keys.iterator();
				while (iterator.hasNext()) {
					SelectionKey key = iterator.next();
					iterator.remove();
					
					requestQueue.offer(key);
				}

			} catch (Exception e) {
				e.printStackTrace();
			}

		}
		
		
	}

	private static void init() {

		try {
			selector = selector.open();

			// 服务端的channel
			ServerSocketChannel channel = ServerSocketChannel.open();
			channel.configureBlocking(false);
			channel.socket().bind(new InetSocketAddress(9001), 100);
			channel.register(selector, SelectionKey.OP_ACCEPT);
		} catch (IOException e) {
		}

		requestQueue = new LinkedBlockingQueue<>(500);
		
		threadPool = Executors.newFixedThreadPool(10);
		for (int i = 0; i < 2; i++) {
			threadPool.submit(new MyWorker());
		}
	}

	private static class MyWorker implements Runnable {

		@Override
		public void run() {
			System.out.println(Thread.currentThread().getName());
			
			while (true) {
				try {
					SelectionKey key = requestQueue.take();
					myHandlerRequest(key);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}

		private void myHandlerRequest(SelectionKey key) throws Exception {
			
			SocketChannel channel = null;
			
			try {
				if (key.isAcceptable()) {
					ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
					channel = serverSocketChannel.accept();
					channel.configureBlocking(false);
					channel.register(selector, SelectionKey.OP_READ);
				}

				else if (key.isReadable()) {
					channel = (SocketChannel) key.channel();

					ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
					int count = channel.read(byteBuffer);

					if (count > 0) {
						byteBuffer.flip();
						channel.register(selector, SelectionKey.OP_WRITE);
					}
				}

				else if (key.isWritable()) {
					ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
					byteBuffer.put("收到".getBytes());
					byteBuffer.flip();

					channel = (SocketChannel) key.channel();
					channel.write(byteBuffer);
					channel.register(selector, SelectionKey.OP_READ);
				}
			} catch (Exception e) {
				e.printStackTrace();
				if (channel != null) {
					channel.close();
				}
			}
		}
		
	}
}
